﻿using SZJT.Framework.Services.Core;
using System.Security.Cryptography.X509Certificates;
using SZJT.Framework.Services;
using SZJT.Framework.Core;
using System.Collections.Generic;
using SZJT.Framework.Adapter;
using System.Text;
using System.Xml;
using System.Web;
using System;

namespace SZJT.Framework.Services
{
    public static class AccountService
    {
        public static string TransformData(string userId, string taskGuid, XmlTransformMessage tranfromMessage)
        {
            var certificate = CertService.GetLocalCert();
            switch (tranfromMessage.DataType.ToUpper())
            {
                case "LOGINTICKET":
                    return DoAcc(taskGuid, userId, tranfromMessage, certificate);
                case "CERTTICKET":
                    return CertLogin(taskGuid, tranfromMessage, certificate);
                default:
                    LoggerHelper.WriteCodePointInfo("登录参数中的DataType缺失或不正确：" + tranfromMessage.DataType);
                    IList<XmlDataElement> resultElements = new List<XmlDataElement>();
                    var resultElement = new XmlDataElement
                    {
                        Name = "UserId",
                        ServiceDataType = ServiceDataType.UNKNOWN,
                        Value = string.Empty
                    };
                    resultElements.Add(resultElement);
                    tranfromMessage.Elements = resultElements;
                    return tranfromMessage.ToString();
            }
        }
        /// <summary>
        /// 执行账号认证操作
        /// </summary>
        /// <param name="taskGuid"></param>
        /// <param name="userId"></param>
        /// <param name="tranfromMessage">认证字符串</param>
        /// <param name="certificate">本地证书</param>
        /// <returns>认证结果</returns>
        private static string DoAcc(string taskGuid, string userId, MessageBase tranfromMessage, X509Certificate2 certificate)
        {
            return string.IsNullOrEmpty(userId)
                       ? AccLogin(taskGuid, tranfromMessage, certificate)
                       : Logout(taskGuid, userId, tranfromMessage);
        }
        /// <summary>
        /// 账号登陆操作
        /// </summary>
        /// <param name="taskGuid"></param>
        /// <param name="tranfromMessage"></param>
        /// <param name="certificate"></param>
        /// <returns>用户标识信息</returns>
        private static string AccLogin(string taskGuid, MessageBase tranfromMessage, X509Certificate2 certificate)
        {
            var userNameElement = tranfromMessage.GetElement("UserName");
            var passwordElement = tranfromMessage.GetElement("Password");
            var timeElement = tranfromMessage.GetElement("EncryptTime");
            var ipAddressElement = tranfromMessage.GetElement("IPAddress");
            if (null == userNameElement || null == passwordElement || null == timeElement || null == ipAddressElement || null == certificate)
                throw new Exception("本地证书为空或登陆参数不正确：" + tranfromMessage);
            IList<XmlDataElement> resultElements = new List<XmlDataElement>();
            var resultElement = new XmlDataElement
            {
                Name = "UserID",
                ServiceDataType = ServiceDataType.UNKNOWN,
                Value = string.Empty
            };
            resultElements.Add(resultElement);
            var localCert = certificate;
            var ipAddress = null == ipAddressElement ? string.Empty : ipAddressElement.Value;
            var userName = null == userNameElement
                               ? string.Empty
                               : CertService.DecryptByPrivateKey(localCert, userNameElement.Value);
            var password = null == passwordElement
                                   ? string.Empty
                                   : CertService.DecryptByPrivateKey(localCert, passwordElement.Value);
            var time = null == timeElement
                               ? string.Empty
                               : CertService.DecryptByPrivateKey(localCert, timeElement.Value);
            if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(time) || !CertService.MatchTime(time))
            {
                resultElement.Value = string.Empty;
            }
            else
            {
                var orgAdapter = AdapterFactory.GetAdapter(Constants.ORG_GUID);
                if (null != orgAdapter && !string.IsNullOrEmpty(orgAdapter.UserId))
                {
                    var resultNode = orgAdapter.TransformData(Constants.ORG_GUID,
                                                              BuildTransData(userName, password, ipAddress, orgAdapter.PublicKeyString));
                    //resultNode.SelectSingleNode("Document[@TaskGuid]").Value = tranfromMessage.TaskGuid;//////
                    return resultNode.InnerXml;
                }
            }
            tranfromMessage.Elements = resultElements;
            return tranfromMessage.ToString();
        }
        /// <summary>
        /// 账号登出操作
        /// </summary>
        /// <param name="taskGuid"></param>
        /// <param name="userId"></param>
        /// <param name="tranfromMessage"></param>
        /// <returns>登出信息</returns>
        private static string Logout(string taskGuid, string userId, MessageBase tranfromMessage)
        {
            //var pool = PermissionManager.GetCertifiedPool(taskGuid);
            //pool.Pool.Remove(userId);
            LoggerHelper.WriteStatusInfo("用户：" + userId + "成功登出组件：" + taskGuid);
            IList<XmlDataElement> resultElements = new List<XmlDataElement>();
            var resultElement = new XmlDataElement
            {
                Name = "UserId",
                ServiceDataType = ServiceDataType.UNKNOWN,
                Value = string.Empty
            };
            resultElements.Add(resultElement);
            tranfromMessage.Elements = resultElements;
            return tranfromMessage.ToString();
        }
        /// <summary>
        /// 证书登陆操作
        /// </summary>
        /// <param name="taskGuid"></param>
        /// <param name="tranfromMessage"></param>
        /// <param name="certificate"></param>
        /// <returns>用户标识信息</returns>
        private static string CertLogin(string taskGuid, MessageBase tranfromMessage, X509Certificate2 certificate)
        {
            var userNameElement = tranfromMessage.GetElement("UserName");
            var encryptTimeElement = tranfromMessage.GetElement("EncryptTime"); //公钥加密时间
            var ipAddressElement = tranfromMessage.GetElement("IPAddress");
            if (null == userNameElement || null == encryptTimeElement || null == ipAddressElement || null == certificate)
                throw new Exception("本地证书为空或登陆参数不正确：" + tranfromMessage);
            IList<XmlDataElement> resultElements = new List<XmlDataElement>();
            var resultElement = new XmlDataElement
            {
                Name = "UserID",
                ServiceDataType = ServiceDataType.UNKNOWN,
                Value = string.Empty
            };
            resultElements.Add(resultElement);
            var localCert = certificate;
            var userName = null == userNameElement
                               ? string.Empty
                               : CertService.DecryptByPrivateKey(localCert, userNameElement.Value);
            var time = null == encryptTimeElement
                                  ? string.Empty
                                  : CertService.DecryptByPrivateKey(localCert, encryptTimeElement.Value);
            var ipAddress = null == ipAddressElement ? string.Empty : ipAddressElement.Value;
            if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(time) || !CertService.MatchTime(time))
            {
                resultElement.Value = string.Empty;
            }
            else
            {
                var orgAdapter = AdapterFactory.GetAdapter(Constants.ORG_GUID);
                if (null != orgAdapter && !string.IsNullOrEmpty(orgAdapter.UserId))
                {
                    var resultNode = orgAdapter.TransformData(Constants.ORG_GUID,
                                                              BuildTransData(userName, ipAddress, orgAdapter.PublicKeyString));
                    //resultNode.SelectSingleNode("Document[@TaskGuid]").Value = tranfromMessage.TaskGuid;//////
                    return resultNode.InnerXml;
                }
            }
            tranfromMessage.Elements = resultElements;
            return tranfromMessage.ToString();
        }
        /// <summary>
        /// 创建账号认证字符串
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <param name="ipAddress"></param>
        /// <param name="pk"></param>
        /// <returns>加密过的账户认证字符串</returns>
        private static XmlNode BuildTransData(string userName, string password, string ipAddress, string pk)
        {
            var xmlDoc = new XmlDocument();
            var sb = new StringBuilder();
            sb.Append(string.Format("<Document TaskGuid=\"{0}\" DataGuid=\"\" DataType=\"LoginTicket\">", Constants.ORG_GUID));
            sb.Append("<UserNameTicket>");
            sb.Append(string.Format("<UserName Type=\"TEXT\">{0}</UserName>", LoginTicket.EncryptByPublicKey(pk, userName)));
            sb.Append(string.Format("<Password Type=\"TEXT\">{0}</Password>", LoginTicket.EncryptByPublicKey(pk, password)));
            sb.Append(string.Format("<EncryptTime Type=\"TEXT\">{0}</EncryptTime>", LoginTicket.EncryptByPublicKey(pk, DateTime.Now.ToString())));
            sb.Append("</UserNameTicket>");
            sb.Append(string.Format("<IPAddress Type=\"TEXT\">{0}</IPAddress>", ipAddress));
            sb.Append("</Document>");
            xmlDoc.LoadXml(sb.ToString());
            return xmlDoc;
        }
        /// <summary>
        /// 创建证书认证字符串
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="ipAddress"></param>
        /// <param name="pk"></param>
        /// <returns>加密过的证书认证字符串</returns>
        private static XmlNode BuildTransData(string userName, string ipAddress, string pk)
        {
            var xmlDoc = new XmlDocument();
            var sb = new StringBuilder();
            sb.Append(string.Format("<Document TaskGuid=\"{0}\" DataGuid=\"\" DataType=\"CertTicket\">", Constants.ORG_GUID));
            sb.Append("<UserNameTicket>");
            sb.Append(string.Format("<UserName Type=\"TEXT\">{0}</UserName>", LoginTicket.EncryptByPublicKey(pk, userName)));
            sb.Append(string.Format("<EncryptTime Type=\"TEXT\">{0}</EncryptTime>", LoginTicket.EncryptByPublicKey(pk, DateTime.Now.ToString())));
            sb.Append("</UserNameTicket>");
            sb.Append(string.Format("<IPAddress Type=\"TEXT\">{0}</IPAddress>", ipAddress));
            sb.Append("</Document>");
            xmlDoc.LoadXml(sb.ToString());
            return xmlDoc;
        }
    }
}